package com.example.spinning.service;

import com.alibaba.fastjson.JSONObject;
import com.example.spinning.bean.Log;
import com.example.spinning.bean.Organ;
import com.example.spinning.bean.User;
import com.example.spinning.mapper.LogMapper;
import com.example.spinning.utils.IPUtils;
import com.example.spinning.utils.Util;
import com.sun.tools.internal.jxc.ap.Const;
import org.apache.ibatis.javassist.*;
import org.apache.ibatis.javassist.bytecode.CodeAttribute;
import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute;
import org.apache.ibatis.javassist.bytecode.MethodInfo;
import org.aspectj.lang.JoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 日志管理
 */
@Service
@Transactional
public class LogService {
    private static final String LOG_CONTENT = "[类名]:%s,[方法]:%s,[参数]:%s,[IP]:%s";

    private String username;
    private String nickname;

    @Autowired
    private LogMapper logMapper;

    public String initUsername(String username) {
        if(!StringUtils.isEmpty(username)){
            this.username = username;
        }
        return this.username;
    }


    public void put(JoinPoint joinPoint, String methodName, String module, String description) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            Log log = new Log();
            //username = ((JwtClient) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
            // 获取当前登录用户
//            MyShiroRealm.ShiroUser shiroUser = (MyShiroRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
//            User user = Util.getCurrentUser();
//          User user = userRepository.findOne(shiroUser.getId());
//            username = shiroUser.getUsername();
//            username = user.getUsername();
            nickname = "小杰";
//            if (StringUtils.isEmpty(username)) {
//                username = Const.USERNAME_IN_CONTEXT != null ? Const.USERNAME_IN_CONTEXT : "未知用户";
//            }

            String ip = IPUtils.getIpAddr(request);
            log.setNickname(nickname);
            log.setModule(module);
            log.setOperation(description);
            log.setIp(ip);
            log.setContent(operateContent(joinPoint, methodName, ip, request));
//            log.setAble(1);
            //insert(log);
            logMapper.addLog(log);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*public Page<Log> page(LogRequest request, Page<Log> page) {
        if(request == null){
            request = new LogRequest();
        }
        request.setIsDeleted(Config.ABLE_CONFIG.ABLE);
        List<Log> logs = baseMapper.page(request,page);
        page.setRecords(logs);
        return page;
    }*/

//    /**
//     * 查询所有日志
//     * @param pageNum
//     * @param request
//     * @return
//     */
//    public PageDto findAll(int pageNum, HttpServletRequest request) {
//        Sort sort = new Sort(Sort.Direction.DESC, "updateAt");
//        List<SpecificationOperator> operators = HttpRequests.getParametersStartingWith(request, "Q_");
//        //增加删除标识的过滤
//        SpecificationOperator isValid = new SpecificationOperator("able", "1", "EQ");
//        operators.add(isValid);
//        MySpecification<Log> mySpecifications = new MySpecification<>(operators);
//        Pageable pageable = new PageRequest(pageNum, 10, sort);
//        Page<Log> page = logRepository.findAll(mySpecifications, pageable);
//        //设置PageDto
//        List<Log> parameters = page.getContent();
//        long total = page.getTotalElements();
//        PageDto pageDto = new PageDto();
//        pageDto.setRows(parameters);
//        pageDto.setTotal(total);
//        return pageDto;
//    }

    public List<Organ> getSpecificLogs(int page, int count, Log log){
        int start = (page-1)*count;
        return logMapper.getSpecificLogs(start,count,log);
    }

    //由名字找到行数
    public int getLogCountByCondition(Log log) {
        return logMapper.getLogCountByCondition(log);
    }

    public String operateContent(JoinPoint joinPoint, String methodName, String ip, HttpServletRequest request) throws ClassNotFoundException, NotFoundException {
        String className = joinPoint.getTarget().getClass().getName();
        Object[] params = joinPoint.getArgs();
        String classType = joinPoint.getTarget().getClass().getName();
        Class<?> clazz = Class.forName(classType);
        String clazzName = clazz.getName();
        Map<String,Object > nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName,params);
        StringBuffer bf = new StringBuffer();
        if (!CollectionUtils.isEmpty(nameAndArgs)){
            Iterator it = nameAndArgs.entrySet().iterator();
            while (it.hasNext()){
                Map.Entry entry = (Map.Entry) it.next();
                String key = (String) entry.getKey();
                String value = JSONObject.toJSONString(entry.getValue());
                bf.append(key).append("=");
                bf.append(value).append("&");
            }
        }
        if (StringUtils.isEmpty(bf.toString())){
            bf.append(request.getQueryString());
        }
        return String.format(LOG_CONTENT, className, methodName, bf.toString(), ip);
    }

    private Map<String,Object> getFieldsName(Class cls, String clazzName, String methodName, Object[] args) throws NotFoundException {
        Map<String,Object > map=new HashMap<String,Object>();

        ClassPool pool = ClassPool.getDefault();
        ClassClassPath classPath = new ClassClassPath(cls);
        pool.insertClassPath(classPath);

        CtClass cc = pool.get(clazzName);
        CtMethod cm = cc.getDeclaredMethod(methodName);
        MethodInfo methodInfo = cm.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
        if (attr == null) {
            // exception
            return map;
        }
        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
        for (int i = 0; i < cm.getParameterTypes().length; i++){
            map.put( attr.variableName(i + pos),args[i]);//paramNames即参数名
        }
        return map;
    }
}
